﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Web.Configuration;
using System.Diagnostics;

namespace EncryptDecryptWebConfig
{
    class WebConfigProtector
    {
        public static string Encrypt(string section, string configPath, string provider)
        {
            string result = string.Empty;
            try
            {
                if (configPath.ToLower().EndsWith("web.config"))
                {
                    if (EncryptWebConfig(section, configPath, provider, ref result))
                    {
                        result = "O arquivo de configuração foi encriptado com sucesso!!";
                    }
                    else
                    {
                        result = "Ocorreu uma falha ao tentar encriptar o arquivo. \n Detalhes: " + result;
                    }
                }
                else
                {
                    Configuration configFile = ConfigurationManager.OpenExeConfiguration(configPath.ToLower().Replace(".config",string.Empty));
                    ConfigurationSection configSection = configFile.GetSection(section);

                    if (!configSection.SectionInformation.IsProtected)
                    {
                        configSection.SectionInformation.ProtectSection(provider);
                        configSection.SectionInformation.ForceSave = true;
                        configFile.Save(ConfigurationSaveMode.Full);
                        result = "O arquivo de configuração foi encriptado com sucesso!!";
                    }
                    else
                    {
                        result = "A sessão informada \""+section+"\" já está encriptada. \n Nenhuma alteração foi realizada.";
                    }
                }
            }
            catch (Exception ex)
            {
                result = "Ocorreu uma falha ao tentar encriptar o arquivo. \n Detalhes: " + ex.ToString(); 
            }

            return result;
        }

        public static string Decrypt(string section, string configPath)
        {
            string result = string.Empty;
            try
            {
                if (configPath.ToLower().EndsWith("web.config"))
                {
                    if (DecryptWebConfig(section, configPath, ref result))
                    {
                        result = "O arquivo de configuração foi decriptado com sucesso!!";
                    }
                    else
                    {
                        result = "Ocorreu uma falha ao tentar decriptar o arquivo. Detalhes: " + result;
                    }
                }
                else
                {
                    Configuration configFile = ConfigurationManager.OpenExeConfiguration(configPath.ToLower().Replace(".config", string.Empty));
                    ConfigurationSection configSection = configFile.GetSection(section);

                    if (configSection.SectionInformation.IsProtected)
                    {
                        configSection.SectionInformation.UnprotectSection();
                        configSection.SectionInformation.ForceSave = true;
                        configFile.Save(ConfigurationSaveMode.Full);
                        result = "O arquivo de configuração foi decriptado com sucesso!!";
                    }
                    else
                    {
                        result = "A sessão informada \"" + section + "\" não está encriptada. \n Nenhuma alteração foi realizada.";
                    }
                }
            }
            catch (Exception ex)
            {
                result = "Ocorreu uma falha ao tentar decriptar o arquivo. \n Detalhes: " + ex.ToString();
            }

            return result;
        }


        #region private methods

        private static bool EncryptWebConfig(string section, string configPath, string provider, ref string errorMessage)
        {
            return EncryptDecryptWebConfig("-pef", section, configPath, provider, ref errorMessage);
        }

        private static bool DecryptWebConfig(string section, string configPath, ref string errorMessage)
        {
            return EncryptDecryptWebConfig("-pdf", section, configPath, string.Empty, ref errorMessage);
        }

        private static bool EncryptDecryptWebConfig(string action, string section, string configPath, string provider, ref string errorMessage)
        {
            string aspnet_regiisPath = ConfigurationManager.AppSettings["ASPNET_REGIIS_Path"];
            aspnet_regiisPath = !string.IsNullOrEmpty(aspnet_regiisPath) ? aspnet_regiisPath : "c:\\Windows\\Microsoft.Net\\Framework\\v4.0.30319";

            Process process = new Process();
            process.StartInfo.FileName = aspnet_regiisPath + "\\aspnet_regiis.exe";
            process.StartInfo.Arguments = string.Format(action + " \"{0}\" \"{1}\"" + (!string.IsNullOrEmpty(provider) ? " -prov " : string.Empty) + "{2}", section, configPath.ToLower().Replace("\\web.config", string.Empty), provider);
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.CreateNoWindow = true;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardError = true;
            process.Start();

            process.WaitForExit();

            bool isSuccess = process.ExitCode.Equals(0);

            if (!isSuccess)
            {
                errorMessage = process.StandardOutput.ReadToEnd() + " " + process.StandardError.ReadToEnd();
            }

            return isSuccess;
        }

        #endregion
    }
}
